package utils

import (
	"fmt"
	"io/ioutil"
	"net"
	"strings"
	"time"
	"golang.org/x/crypto/ssh"
	"log"
	"github.com/mitchellh/go-homedir"
	"github.com/gogf/gf/os/glog"
)

func DialSSH(user, password, keypath, ip string, port int) (*ssh.Client, error) {
	var (
		auth         []ssh.AuthMethod
		addr         string
		clientConfig *ssh.ClientConfig
		config       ssh.Config
		// err          error
	)
	// get auth method
	auth = make([]ssh.AuthMethod, 0)
	if password != "" {
		connstr := fmt.Sprintf("connect to %s@%s:%d with password",user, ip, port)
		glog.Info(connstr)
		auth = append(auth, ssh.Password(password))
	} else {
		connstr := fmt.Sprintf("connect to %s@%s:%d with sectetKey",user, ip, port)
		glog.Info(connstr)
		auth = append(auth, publicKeyAuthFunc(keypath))
	}
	config = ssh.Config{
		Ciphers: []string{"aes128-ctr", "aes192-ctr", "aes256-ctr", "aes128-gcm@openssh.com", "arcfour256", "arcfour128", "aes128-cbc", "3des-cbc", "aes192-cbc", "aes256-cbc"},
	}
	clientConfig = &ssh.ClientConfig{
		User:    user,
		Auth:    auth,
		Timeout: 10 * time.Second,
		Config:  config,
		HostKeyCallback: func(hostname string, remote net.Addr, key ssh.PublicKey) error {
			return nil
		},
	}
	
	// glog.Info("use clientConfig: ",clientConfig)
	// glog.Info("AuthMethod: ", auth)
	// connect to ssh
	addr = fmt.Sprintf("%s:%d", ip, port)
	glog.Info("connect to ", addr)
	return ssh.Dial("tcp", addr, clientConfig)
}

func ClearNewline(str string) string {
	return strings.TrimRight(strings.Replace(str, "\r\n", "\n", -1), "\n")
}

func publicKeyAuthFunc(kPath string) ssh.AuthMethod {
    keyPath, err := homedir.Expand(kPath)
    if err != nil {
        log.Fatal("find key's home dir failed", err)
    }
    key, err := ioutil.ReadFile(keyPath)
    if err != nil {
        log.Fatal("ssh key file read failed", err)
    }
    // Create the Signer for this private key.
    signer, err := ssh.ParsePrivateKey(key)
    if err != nil {
        log.Fatal("ssh key signer failed", err)
    }
    return ssh.PublicKeys(signer)
}